home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / qwktxt45.zip / QWKTXT45.C < prev    next >
C/C++ Source or Header  |  1992-07-22  |  18KB  |  536 lines

  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <ctype.h>
  4. #include <direct.h>
  5. #include <dos.h>
  6. #include <errno.h>
  7. #include <process.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10.  
  11. #define STUFF_SIZE 129                      /* buffer size for fgets        */
  12. #define ASIZE 6550                          /* determines # of conferences  */
  13.                                             /* we can handle                */
  14.  
  15. #define VERSION  "4.50"                     /* version number               */
  16. #define REL_DATE "July 22, 1992"            /* release date (keep format!)  */
  17.  
  18. #define ARC     1                           /* Result code for ARC(TM)      */
  19. #define ZOO     2                           /* Result code for ZOO          */
  20. #define ARJ     3                           /* Result code for ARJ          */
  21. #define LHARC   4                           /* Result code for LHARC        */
  22. #define LHA     5                           /* Result code for LHA          */
  23. #define ZIP     6                           /* Result code for ZIP          */
  24. #define UNKNOWN 10                          /* Result code for UNKNOWN      */
  25.  
  26. unsigned personal = 0;                      /* count of personal messages   */
  27. unsigned MsgsPerConference = 0;             /* count of messages/conference */
  28. unsigned TotalMsgsInQWK = 0;                /* count of messages in packet  */
  29.  
  30. int arctype = 0;                            /* archive type returned from   */
  31.                                             /* whicharc() function          */
  32.  
  33. char zipflag;                               /* flag telling whether to use  */
  34.                                             /* pkunzip.exe or unzip.exe     */
  35.  
  36. struct hdr                                  /* message header structure     */
  37. {
  38.    char _private;                           /* first byte is privacy flag   */
  39.                                             /* ' ' means mail has been read */
  40.                                             /* '-' means not read           */
  41.                                             /* '+' means private message    */
  42.    char _msg[7];                            /* message number in ASCII      */
  43.    char _date[8];                           /* date in ASCII (mm-dd-yy)     */
  44.    char _time[5];                           /* time in ASCII (hh:mm)        */
  45.    char _to[25];                            /* name of receiver             */
  46.    char _from[25];                          /* name of sender               */
  47.    char _subj[37];                          /* message subject              */
  48.    char _ref[8];                            /* msg refers to this msg #     */
  49.    char _count[6];                          /* # of 128-byte blocks in msg  */
  50.    char _junk2[6];                          /* these 6 bytes are, in order: */
  51.                                             /* 1. killed msg flag           */
  52.                                             /*    225 (0xE1) == active      */
  53.                                             /*    226 (0xE2) == killed      */
  54.                                             /* 2. conference number         */
  55.                                             /* 3-6. Reserved for future use */
  56. } header;
  57.  
  58. struct conf                                 /* conference header structure  */
  59. {
  60.    int _num;                                /* conference number            */
  61.    int _msgs;                               /* # of msgs in conference      */
  62.    char _name[15];                          /* conf. name (14 chars max)    */
  63. } confs[ASIZE];
  64.  
  65. /* prototypes for ANSI C */
  66.  
  67. void strip(char *s);
  68. char *byp(char *s);
  69. void _cdecl main(int argc, char **argv);
  70. int  nummsg(int n);
  71. int  readblk(FILE *fp, char *buff);
  72. int  readhdr(FILE *fp);
  73. void strncp(char *d, char *s, int n);
  74. void sep(FILE *fp);
  75. void _cdecl erase(char *pathname);
  76. int WhichArc(char *pName);
  77.  
  78.  
  79. void strip(char *s)              /* strip trailing whitespace from string s */
  80. {
  81.    char *p;
  82.  
  83.    p = s;
  84.    while (*p)
  85.       p++;
  86.    while (p > s && isspace(*--p))
  87.       *p = 0;
  88. }
  89.  
  90. char *byp(char *s)              /* bypass unwanted whitespace from string s */
  91. {
  92.    while (isspace(*s))
  93.       s++;
  94.    return(s);
  95. }
  96.  
  97. void _cdecl main(int argc, char **argv)
  98. {
  99.    FILE *ifp, *ofp;
  100.    int  i = 0, j;
  101.    int  cn, Acc_confs;
  102.    char *sp;
  103.    char stuff[STUFF_SIZE];
  104.    char BBS_name[80];
  105.    char BBS_location[80];
  106.    char BBS_phone_number[25];
  107.    char Packet_date[12];
  108.    char Packet_time[9];
  109.    char User_name[25];
  110.    char temp[25];
  111.    char *unavailable = "Not provided.";
  112.    char fqpname[81];                        /* fully qualified path name    */
  113.  
  114.    TotalMsgsInQWK = 0;
  115.    MsgsPerConference = 0;
  116.  
  117.    printf("%c[2J",27);
  118.    printf("QWK2TXT %s QWK -> TXT converter\n", VERSION);
  119.    printf("Public Domain as of %s\n\n", REL_DATE);
  120.  
  121.    if( (argc != 2)  &&  (argc != 3) )    /* check for proper number of args */
  122.    {
  123.       printf("\n\tusage: qwk2txt filename.qwk");
  124.       printf("\n\t -or-  qwk2txt filename.qwk P|U\n\n");
  125.       printf("\n\twhere: filename.qwk is your qwk file");
  126.       printf("\n\t       P = use PKUNZIP.EXE");
  127.       printf("\n\t       U = use UNZIP.EXE\n");
  128.       printf("\n\tNOTE: ONLY one of P or U may be used and if used, the");
  129.       printf("\n\t      filename.qwk MUST be in .ZIP format. P or U is");
  130.       printf("\n\t      not needed if the file is in another archive format.\n\n");
  131.       exit(1);
  132.    }
  133.  
  134.    zipflag = toupper(argv[2][0]);
  135.  
  136.    printf("Decompressing QWK file...One moment, please...\r");
  137.  
  138.    if(mkdir("QWK$TMP") == -1)
  139.    {
  140.       printf("\n\tError: Can't create temporary subdirectory QWK$TMP.");
  141.       exit(1);
  142.    }
  143.  
  144.    arctype = WhichArc(argv[1]);
  145.  
  146.    switch(arctype)
  147.    {
  148.       case -1:
  149.          printf("\n\tFile %s not found.", argv[1]);
  150.          exit(1);
  151.          break;
  152.       case UNKNOWN:
  153.          printf("\n\tArchive method of %s is unknown.", argv[1]);
  154.          exit(1);
  155.          break;
  156.       case ARC:
  157.          chdir("QWK$TMP");
  158.          sprintf(fqpname, "arc x ..\\%s >nul", argv[1]);
  159.          break;
  160.       case ZOO:
  161.          chdir("QWK$TMP");
  162.          sprintf(fqpname, "zoo x ..\\%s >nul", argv[1]);
  163.          break;
  164.       case ARJ:
  165.          chdir("QWK$TMP");
  166.          sprintf(fqpname, "arj x ..\\%s >nul", argv[1]);
  167.          break;
  168.       case LHARC:
  169.          chdir("QWK$TMP");
  170.          sprintf(fqpname, "lharc x ..\\%s >nul", argv[1]);
  171.          break;
  172.       case LHA:
  173.          chdir("QWK$TMP");
  174.          sprintf(fqpname, "lha x ..\\%s >nul", argv[1]);
  175.          break;
  176.       case ZIP:
  177.          chdir("QWK$TMP");
  178.          if(zipflag == 'P')
  179.             sprintf(fqpname, "pkunzip ..\\%s >nul", argv[1]);
  180.          else if(zipflag == 'U')
  181.             sprintf(fqpname, "unzip ..\\%s >nul", argv[1]);
  182.          else
  183.             sprintf(fqpname, "pkunzip ..\\%s >nul", argv[1]);
  184.          break;
  185.    }
  186.  
  187.    system(fqpname);                                  /* decompress the file */
  188.  
  189.    printf("                                              \n\n");
  190.  
  191.    if ((ifp = fopen("control.dat", "r")) == NULL)       /* open control.dat */
  192.    {
  193.       printf("\n\tRequired file CONTROL.DAT not found.");
  194.       exit(1);
  195.    }
  196.  
  197.    if(fgets(stuff,STUFF_SIZE,ifp) != NULL)  /* get BBS' name                */
  198.    {
  199.       strip(stuff);
  200.       strcpy(BBS_name,stuff);
  201.    }
  202.  
  203.    if(fgets(stuff,STUFF_SIZE,ifp) != NULL)  /* get BBS' city/state          */
  204.    {
  205.       strip(stuff);
  206.       if(stuff[0] == 0)
  207.          strcpy(BBS_location,unavailable);
  208.       else
  209.          strcpy(BBS_location,stuff);
  210.    }
  211.  
  212.    if(fgets(stuff,STUFF_SIZE,ifp) != NULL)  /* get BBS' phone number        */ 
  213.    {
  214.       strip(stuff);
  215.       strcpy(BBS_phone_number,stuff);
  216.    }
  217.  
  218.    fgets(stuff, STUFF_SIZE, ifp);        /* toss sysop name into bit-bucket */
  219.    fgets(stuff, STUFF_SIZE, ifp);        /* toss door reg. # and BBS ID too */
  220.  
  221.    if(fgets(stuff,STUFF_SIZE,ifp) != NULL)  /* get packet date & time       */
  222.    {
  223.       strip(stuff);
  224.       strcpy(temp,stuff);
  225.    }
  226.  
  227.    for(i=0; i<10; i++)                     /* strip packet date from string */
  228.       Packet_date[i] = temp[i];
  229.    Packet_date[10] = '\0';
  230.  
  231.    for(i=11; i<19; i++)                    /* strip packet time from string */
  232.       Packet_time[i-11] = temp[i];
  233.    Packet_time[8] = '\0';
  234.  
  235.    if(fgets(stuff,STUFF_SIZE,ifp) != NULL)  /* get user's name              */
  236.    {
  237.       strip(stuff);
  238.       strcpy(User_name,stuff);
  239.    }
  240.  
  241.    for (i=0; i < 3; i++)                  /* Skip over Qmail menu filename, */
  242.       fgets(stuff, STUFF_SIZE, ifp);      /* and two ASCII 0's              */
  243.  
  244.    fgets(stuff, STUFF_SIZE, ifp);                /* get ASCII value of # of */
  245.    strip(stuff);                                 /* conferences available   */
  246.    Acc_confs = atoi(stuff);                      /* and convert it to int   */
  247.  
  248.    cn = i = 0;
  249.    for (;;)                             /* loop to identify all conferences */
  250.    {
  251.       if (!fgets(stuff, STUFF_SIZE, ifp))   
  252.          break;
  253.       strip(stuff);
  254.       if (stuff[0] == 0)
  255.          break;
  256.       if (sscanf(stuff, "%d", &i) != 1)            /* get conference number */
  257.       {                                            /* and convert to an int */
  258.          i = 1;
  259.          break;
  260.       }
  261.       if (!fgets(stuff, STUFF_SIZE, ifp))            /* get conference name */
  262.       {
  263.          printf("\n\tCorrupted conference name in CONTROL.DAT.");
  264.          exit(1);
  265.       }
  266.       strip(stuff);
  267.       confs[cn]._num = i;
  268.       confs[cn]._msgs = 0;
  269.       strcpy(confs[cn++]._name, byp(stuff));
  270.    }
  271.    if ((ofp = fopen("messages.txt", "w")) == NULL)      /* open output file */
  272.    {
  273.       printf("\n\tUnable to open MESSAGES.TXT for output.");
  274.       exit(1);
  275.    }
  276.  
  277.    sep(ofp);                                              /* separate areas */
  278.  
  279.    fprintf(ofp, "        BBS Name: %s\n",   BBS_name);
  280.    fprintf(ofp, "    BBS Location: %s\n",   BBS_location);
  281.    fprintf(ofp, "BBS Phone Number: %s\n",   BBS_phone_number);
  282.    fprintf(ofp, "     Packet Date: %s\n",   Packet_date);
  283.    fprintf(ofp, "     Packet Time: %s\n",   Packet_time);
  284.    fprintf(ofp, "       User Name: %s\n\n", User_name);
  285.  
  286.    fprintf(ofp, "You have access to %d conference%s.\n", Acc_confs,
  287.      (Acc_confs == 1) ? "" : "s");
  288.  
  289.    sep(ofp);                    /* separate info above from actual messages */
  290.  
  291.    printf("Indexing conference: ");  /* read *.NDX files and save that info */
  292.    for (i = 0; i < cn; i++)   
  293.       confs[i]._msgs = nummsg(confs[i]._num);
  294.  
  295.    putchar('\r');
  296.    for(i=0; i < 30; i++)                /* get rid of "Indexing..." message */
  297.       putchar(' ');                     /* (only for aesthetics)            */
  298.  
  299.    fclose(ifp);                    /* finished with CONTROL.DAT so close it */
  300.  
  301.    if ((ifp = fopen("messages.dat", "rb")) == NULL)  /* open message packet */
  302.    {
  303.       printf("Unable to open required file MESSAGES.DAT.");
  304.       fclose(ofp);
  305.       exit(1);
  306.    }
  307.    if (readblk(ifp, stuff))   /* read in 1st record with Sparky's copyright */
  308.    {                          /* abort if we can't read for some reason     */
  309.       printf("\n\tCan't read Sparkware's copyright message in MESSAGES.DAT.");
  310.       fclose(ofp);
  311.       exit(1);
  312.    }
  313.  
  314.    for (i = 0; i < cn; i++)         /* main loop -- do for every conference */
  315.    {
  316.       printf("\rWorking on Conference %d [%s]     ", i, confs[i]._name);
  317.  
  318.       TotalMsgsInQWK += MsgsPerConference;
  319.  
  320.       MsgsPerConference = 0;          /* reset variable for next conference */
  321.  
  322.       while (confs[i]._msgs--)    /* as long as the conference has messages */
  323.       {
  324.          if (readhdr(ifp)) /* read the message header or abort if not found */
  325.          {
  326.             printf("\n\tCan't read message header in MESSAGES.DAT file.");
  327.             printf("\n\t\tConference: %d [%s]", i, confs[i]._name);
  328.             printf("\n\t\t Message #: %d", confs[i]._msgs);
  329.             fclose(ofp);
  330.             exit(1);
  331.          }
  332.                       /* keep user's interest up by displaying useless info */
  333.          fprintf(ofp, "Conference: %s\n", confs[i]._name);
  334.          strncp(stuff, header._msg, 7);
  335.          fprintf(ofp, "Message:    %u\n", atoi(stuff));
  336.          MsgsPerConference += 1;      /* increment conference message count */
  337.          strncp(stuff, header._from, 25);
  338.          strip(stuff);
  339.          fprintf(ofp, "From:       %s\n", stuff);
  340.          strncp(stuff, header._to, 25);
  341.          strip(stuff);
  342.          fprintf(ofp, "To:         %s\t", stuff);
  343.          if( strcmp( stuff, User_name) == 0)
  344.          {
  345.             personal += 1;
  346.             if(header._private == 43)     /* is message private and unread? */
  347.             {                       /* flag message as private and personal */
  348.                fprintf(ofp, "[RECEIVER ONLY]\n");
  349.             }
  350.             else
  351.             {                        /* flag message as public and personal */
  352.                fprintf(ofp, "[PUBLIC]\n");
  353.             }
  354.          }
  355.          else
  356.             fprintf(ofp, "\n");
  357.          strncp(stuff, header._subj, 37);
  358.          strip(stuff);
  359.          fprintf(ofp, "Subject:    %s\n", stuff);
  360.          strncp(stuff, header._date, 8);
  361.          strncp(&stuff[20], header._time, 5);
  362.          fprintf(ofp, "Date:       %s %s\n\n", stuff, &stuff[20]);
  363.          strncp(stuff, header._count, 6);
  364.          j = atoi(stuff);            /* get # of 128-byte blocks in message */
  365.          while (--j)                                  /* read in each block */
  366.          {
  367.             if (readblk(ifp, stuff))
  368.             {
  369.                fclose(ofp);
  370.                exit(1);
  371.             }
  372.             stuff[128] = 0;
  373.             if (j == 1)
  374.                strip(stuff);
  375.             for (sp = stuff; *sp; sp++)
  376.                if((unsigned char)*sp == 0xE3) /* if π found, output newline */
  377.                   fprintf(ofp, "\n");
  378.                else
  379.                   putc(*sp, ofp);
  380.          }
  381.          sep(ofp);
  382.       }
  383.    }
  384.  
  385.    fclose(ofp);                             /* close text file messages.txt */
  386.    fclose(ifp);                           /* close binary file messages.dat */
  387.  
  388.    printf("\n\nTotal Messages in %s: %u\n", argv[1], TotalMsgsInQWK);
  389.  
  390.  
  391.    system("copy messages.txt .. >nul");
  392.  
  393.    erase(".");                       /* Erase all files in the temporary    */
  394.                                      /*  subdirectory - should work with    */
  395.                                      /*  DOS 3.3 and DOS 5.0 without having */
  396.                                      /*  the query from COMMAND.COM         */
  397.  
  398.    chdir("..");
  399.    rmdir("QWK$TMP");
  400.    exit(0);
  401. }
  402.  
  403. int nummsg(int n)                      /* Read Index files and process them */
  404. {
  405.    FILE *ifp;
  406.    int  i, j, ch;
  407.    char name[20];
  408.    char five[5];
  409.  
  410.    sprintf(name, "%03d.ndx", n);
  411.    i = 0;
  412.    if ((ifp = fopen(name, "rb")) != NULL)
  413.    {
  414.       printf("%03d\b\b\b", n);         /* only show conf # if file is found */
  415.  
  416.                                        /* I can't explain this next routine */
  417.                                        /* because it isn't mine. I found it */
  418.                                        /* scrawled in an old MSC manual.    */
  419.                                        /* It does work, however, for both   */
  420.                                        /* TC and MSC.  MSBIN is a damnable  */
  421.       for (;;)                         /* choice for indexing...            */
  422.       {
  423.          for (j = 0; j < 5; j++)
  424.          {
  425.             if ((ch = getc(ifp)) == EOF)
  426.                ch = 26;
  427.             five[j] = ch;
  428.          }
  429.          for (j = 0; j < 5 && five[j] == 26; j++)
  430.             ;
  431.          if (j == 5)
  432.             break;
  433.          i++;
  434.       }
  435.       fclose(ifp);
  436.    }
  437.    return(i);
  438. }
  439.  
  440. int readblk(FILE *fp, char *buff)
  441. {
  442.    int i, ch;
  443.  
  444.    for (i = 0; i < 128; i++)
  445.       if ((ch = getc(fp)) == EOF)
  446.          return(1);
  447.       else
  448.          *buff++ = ch;
  449.    return(0);
  450. }
  451.  
  452. int readhdr(FILE *fp)
  453. {
  454.    if ( fread(&header, 1, sizeof(struct hdr), fp) != sizeof(struct hdr) )
  455.       return(1);
  456.    else
  457.       return(0);
  458. }
  459.  
  460. void strncp(char *d, char *s, int n)       /* this was for the CP/M version */
  461. {
  462.    while (n-- && (*d++ = *s++))
  463.       ;
  464.    *d = 0;
  465. }
  466.  
  467. void sep(FILE *fp)
  468. {
  469.    int i;
  470.  
  471.    putc('\n',fp);
  472.    for (i = 0; i < 70; i++)
  473.       putc('-',fp);
  474.    putc('\n',fp);
  475. }
  476.  
  477. void _cdecl erase(char *pathname)            /* routine to erase temp files */
  478. {
  479.    char tmp[127];
  480.    char pattern[127];
  481.    int  ok;
  482.  
  483.    struct find_t fileinfo;
  484.  
  485.    sprintf(pattern, "%s\\*.*", pathname);
  486.    ok = _dos_findfirst(pattern,0,&fileinfo);
  487.  
  488.    if(ok != 0)
  489.       return;
  490.  
  491.    while(!ok)
  492.    {
  493.       sprintf(tmp, "%s\\%s", pathname, fileinfo.name);
  494.       unlink(tmp);
  495.       ok = _dos_findnext(&fileinfo);
  496.    }
  497. }
  498.  
  499. int WhichArc(char *pName)
  500. {
  501.    FILE  *afp;
  502.    unsigned char archeader[128];
  503.    int   c, i, n;
  504.  
  505.    memset(archeader, 0, sizeof(archeader));
  506.    afp = fopen(pName, "rb");
  507.    if (afp == NULL) return -1;
  508.    n = fread(archeader, sizeof(unsigned char), sizeof(archeader) - sizeof(unsigned char), afp);
  509.    fclose(afp);
  510.  
  511.    if (n <= 0) return -1;
  512.  
  513.    if (n >= 7 && n >= archeader[0] + 2)
  514.    {
  515.       for (c = 0, i = archeader[0]; i--; c += (archeader+2)[i]);
  516.       if ((c & 0x00FF) == archeader[1] &&
  517.           archeader[2] == '-'          &&
  518.           archeader[3] == 'l'          &&
  519.           archeader[4] == 'h'          &&
  520.           archeader[6] == '-') return (archeader[5] > '1') ? LHA : LHARC;
  521.    }
  522.  
  523.    if (n >= 2)
  524.    {
  525.       if (archeader[0] == 0x60 && archeader[1] == 0xEA) return ARJ;
  526.       if (archeader[0] == 'P'  && archeader[1] == 'K')  return ZIP;
  527.    }
  528.  
  529.    if (n >= 3
  530.       && archeader[0] == 'Z' && archeader[1] == 'O' && archeader[2] == 'O') return ZOO;
  531.  
  532.    if (n >= 25 && archeader[0] == 0x1A) return ARC;
  533.  
  534.    return UNKNOWN;
  535. }
  536.